package ar.uba.fi.tecnicas.juego;

import java.util.Collection;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;

import ar.uba.fi.tecnicas.fabrica.*;

public class Juego extends Observable implements Observer
{
	public static final Juego instancia = new Juego();
	private ConfiguracionJuego configuracion = ConfiguracionJuego.instancia;
	
	private Jugador jugador;
	private Timer ticker;
	private Tiempo tiempo = Tiempo.instancia;
	
	private long tiempoComienzoDelDia;
	private long diasTranscurridos;
	
	private boolean tiempoCongelado; 
	
	private Juego()
	{	
		this.tiempoCongelado = true;
		this.diasTranscurridos = 0;

		this.ticker = new Timer();
		
		this.ticker.scheduleAtFixedRate(
			new TimerTask() {
				public void run(){ Juego.instancia.tick(); };
			}, 
			0, 
			this.configuracion.getMilliPorTick()
		);
		
		this.tiempoComienzoDelDia = tiempo.transcurrido();
	}
	
	public void crearJugador(String nombre)
	{		
		this.jugador = new Jugador(nombre, this.configuracion.capitalInicial);
		this.jugador.addObserver(this);
	}
	
	public Jugador getJugador()
	{
		return this.jugador;
	}

	public Collection<TipoProducto> getTiposProducto()
	{
		return ConfiguracionTipoProducto.instance.getItems();
	}
	
	public Collection<TipoMaquina> getTiposMaquina()
	{
		return ConfiguracionTipoMaquina.instance.getItems();
	}
	
	public Collection<Transformacion> getTransformaciones()
	{
		return ConfiguracionTransformaciones.instance.getItems();
	}
	
	public Collection<Terreno> getTerrenos()
	{
		return ConfiguracionTerreno.instance.getItems();
	}
	
	public Collection<TipoMateriaPrima> getTiposMateriaPrima()
	{
		return ConfiguracionTipoMateriaPrima.instance.getItems();
	}

	public void tick()
	{
		if(!this.tiempoCongelado)
		{
			Exception exception = null;
			this.setChanged();

			this.tiempo.pausar();
			
			if(this.tiempoTranscurridoDelDia() > this.configuracion.getMillisPorDia())
			{
				this.empezarNuevoDia();			
				this.getJugador().contabilizarGanancias();	
			}
			try
			{
				this.getJugador().producir();
			}
			catch (Exception e) 
			{
				exception = e; 
			}
			
			this.notifyObservers(exception);
	
			this.tiempo.reanudar();
		}
	}
	
	public void congelarTiempo()
	{
		if(!this.tiempoCongelado)
		{
			this.tiempo.pausar();
			this.tiempoCongelado = true;
		}
	}
	
	public void descongelarTiempo()
	{
		if(this.tiempoCongelado)
		{
			this.tiempo.reanudar();
			this.tiempoCongelado = false;
		}
	}

	public boolean tiempoCongelado()
	{
		return this.tiempoCongelado;
	}
	
	public String getHoraDelDia()
	{
		float hora = (float)tiempoTranscurridoDelDia() * 24 / (float)this.configuracion.getMillisPorDia();
		int horaInt = (int)hora; 
		float mins = (float)(hora - horaInt) * 60;
		int minsInt = (int)mins;
		
		String horaStr = (horaInt < 10 ? "0" : "") + String.valueOf(horaInt); 
		String minStr = (minsInt < 10 ? "0" : "") + String.valueOf(minsInt);
		
		return horaStr + ":" + minStr;
	}
	
	private long tiempoTranscurridoDelDia()
	{
		return this.tiempo.transcurrido() - this.tiempoComienzoDelDia;
	}
	
	private void empezarNuevoDia()
	{
		this.diasTranscurridos++;
		this.tiempoComienzoDelDia = this.tiempo.transcurrido();
	}	
	
	public void update(Observable observable, Object args)
	{
		this.setChanged();
		this.notifyObservers();
	}
}
